﻿using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using PlatformUW.Contracts;
using PlatformUW.Entities;
using PlatformUW.Entities.DataShaping;
using PlatformUW.Entities.Dtos;
using PlatformUW.Entities.RequestFeatures;
using System.Numerics;

namespace PlatformUW.API.Controllers
{
    [Route("api/player")]
    [ApiController]
    public class PlayerController : ControllerBase
    {
        private readonly IRepositoryWrapper repositoryWrapper;
        private readonly ILogger<PlayerController> logger;
        private readonly IMapper mapper;

        public PlayerController(IRepositoryWrapper repositoryWrapper,
            ILogger<PlayerController> logger,
            IMapper mapper)
        {
            this.repositoryWrapper = repositoryWrapper;
            this.logger = logger;
            this.mapper = mapper;
        }

        [HttpGet("all")]
        public async Task<IActionResult> GetAllPlayers([FromQuery]PlayerParameter parameter)
        {
            try
            {
                if (!parameter.ValidateDateRange())
                {
                    return BadRequest("Invalid date range.");
                }

                var players = await repositoryWrapper.Player.GetAllPlayersAsync(parameter);
                Response.Headers.Append("X-Pagination", Newtonsoft.Json.JsonConvert.SerializeObject(players.MetaData));
                var result = mapper.Map<IEnumerable<PlayerDto>>(
                    players).ShapeData(parameter.Fields);
                return Ok(result);


            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message, "Alarm");
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
            }
        }

        [HttpGet("{id}", Name = "playerById")]
        public IActionResult GetPlayerById(Guid id)
        {
            try
            {
                var player = repositoryWrapper.Player.GetPlayerByIDAsync(id);
                if (player == null)
                {
                    return NotFound();
                }
                var result = mapper.Map<PlayerDto>(player.Result);
                return Ok(result);
            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message, "Alarm");
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
            }
        }

        [HttpGet("{id}/characters")]
        public IActionResult GetPlayerWithCharacterById(Guid id)
        {
            try
            {
                var player = repositoryWrapper.Player.GetPlayerWithCharByIdAsync(id);
                if (player == null)
                {
                    return NotFound();
                }
                var result = mapper.Map<PlayerWithCharacterDto>(player.Result);
                return Ok(result);
            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message, "Alarm");
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
            }
        }

        [HttpPost("add")]
        public IActionResult AddPlayer([FromBody]PlayerForCreateDto player)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest("请求数据无效");
                }
                var playerEntity = mapper.Map<Player>(player);
                repositoryWrapper.Player.AddAsync(playerEntity);
                repositoryWrapper.SaveAsync();

                var createPlayer = mapper.Map<PlayerDto>(playerEntity);
                return CreatedAtRoute("playerById", new  {id = createPlayer.Id}, createPlayer);

            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message, "Alarm");
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
            }
        }

        [HttpPut("update/{id}")]
        public async Task<IActionResult> UpdatePlayer(Guid id, [FromBody]PlayerForUpdateDto player)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest("请求数据无效");
                }
                var playerEntity = await repositoryWrapper.Player.GetPlayerByIDAsync(id);
                if (playerEntity == null)
                {
                    return NotFound("需要修改的玩家不存在");
                }

                mapper.Map(player, playerEntity);

                await repositoryWrapper.Player.UpdateAsync(playerEntity);
                await repositoryWrapper.SaveAsync();

                return NoContent();
            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message, "Alarm");
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
            }
        }


        [HttpDelete("delete/{id}")]
        public async Task<IActionResult> DeletePlayer(Guid id)
        {
            try
            {
                var playerEntity = await repositoryWrapper.Player.GetPlayerWithCharByIdAsync(id);
                if (playerEntity == null)
                {
                    return BadRequest("需要删除的玩家不存在");
                }

                if (playerEntity.characters.Any())
                {
                    return BadRequest("该玩家有关联的人物角色，不能删除");
                }

                await repositoryWrapper.Player.DeleteAsync(playerEntity);
                await repositoryWrapper.SaveAsync();
                return Ok();
            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message, "Alarm");
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
            }
        }
    }
}
